/** @file    JabberGloox10.cpp
 *  @author  Alessandro Polo
 *  @version $Id: JabberGloox10.cpp 2821 2010-08-01 11:44:26Z alex $
 *  @brief
 * File containing methods for the JabberGloox10 class.
 * The header for this class can be found in JabberGloox10.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include "JabberGloox10.h"
 #include <core/User.h>

 #include <client.h>
 #include <message.h>
 #include <messagesession.h>
 #include <rostermanager.h>
 #include <error.h>

using namespace wosh;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS

JabberGloox10::JabberGloox10( wosh::BundleGeneric& bundle )
	: JabberGlooxImpl(bundle) {
 }

JabberGloox10::~JabberGloox10() {
	Log(LOG_DEBUG, ":~JabberGloox10(): Destroying.." );
	if ( isThreadRunning() ) {
		Log(LOG_WARNING, ":~JabberGloox10(): Still running! Forcing quitThread.." );
		quitThread(30000);
	 }
 }

//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////// MESSAGING

bool JabberGloox10::sendMessage( const std::string& user, const std::string& message ) {
	if ( !isThreadRunning() ) return false;
	if ( this->xmppJclient == NULL ) return false;
	Log(LOG_VERBOSE, ":sendMessage(): sending '%s' to %s..", message.c_str(), user.c_str() );
	gloox::Message gMsg( gloox::Message::Normal, gloox::JID(user), message, "", "", "" );
	this->xmppJclient->send( gMsg );
	// well, I can only HOPE that message was sent/received!
	return true;
 }

/////////////////////////////////////////////////////////////////////////////////////////////////// MESSAGING
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////// MessageHandler INTERFACE

void JabberGloox10::handleMessage( const gloox::Message& msg, gloox::MessageSession* ) {
	if ( Log.isDebug() )
		Log(LOG_DEBUG, ":handleMessage(): %s by %s", msg.body().c_str(), msg.from().bare().c_str() );
	if ( msg.error() != NULL ) {
		Log(LOG_WARNING, ":handleMessage(): Stanza Error#%d [%s]", (int)msg.error()->error(), msg.error()->text().c_str() );
		return;
	 }
	if ( this->jabbListener == NULL ) return;
	this->jabbListener->jabbbot_Message( msg.from().bare(), msg.body(), this );
 }

//////////////////////////////////////////////////////////////////////////////////// MessageHandler INTERFACE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////// PresenceHandler INTERFACE

void JabberGloox10::handlePresence( const gloox::Presence& presence ) {
	Log(LOG_VERBOSE, ":handlePresence(): status of %s is '%s' !", presence.from().full().c_str(), presence.status().c_str() );
	// check if it refers to myself. this is periodic on most servers
	if ( this->xmppAccountName == presence.from().bare() ) {
		// mmh.. great i hope so! but we don't notify that..
		return;
	 }
	if ( this->jabbListener == NULL ) return;
	// eval and forward the state of the user
	int status = User::PRESENCE_UNKNOWN;
	switch( presence.presence() ) {
		case gloox::Presence::Available:
		case gloox::Presence::Chat:			status = User::PRESENCE_ONLINE;			break;
		case gloox::Presence::Away:
		case gloox::Presence::XA: 			status = User::PRESENCE_ONLINE_AWAY;	break;
		case gloox::Presence::DND:			status = User::PRESENCE_ONLINE_DND;		break;
		case gloox::Presence::Unavailable:	status = User::PRESENCE_OFFLINE;		break;
		default:							status = User::PRESENCE_UNKNOWN;		break;
	 }
	this->jabbListener->jabbbot_UserStatus( presence.from().bare(), status, presence.status(), this );
 }

/////////////////////////////////////////////////////////////////////////////////// PresenceHandler INTERFACE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// SubscriptionHandler INTERFACE

void JabberGloox10::handleSubscription( const gloox::Subscription& subscription ) {
	int status = _JabberGloox_Subscription_Unknown;
	switch ( subscription.subtype() ) {
		case gloox::Subscription::Subscribe: {
				status = _JabberGloox_Subscription_Subscribe;
				Log(LOG_INFO, ":handleSubscription(): User %s requests to Subscribe!", subscription.from().full().c_str() );
				break;
			 }
		case gloox::Subscription::Subscribed:  {
				status = _JabberGloox_Subscription_Subscribed;
				Log(LOG_INFO, ":handleSubscription(): User %s Subscribed!", subscription.from().full().c_str() );
				break;
			 }
		case gloox::Subscription::Unsubscribe: {
				status = _JabberGloox_Subscription_UnSubscribe;
				Log(LOG_INFO, ":handleSubscription(): User %s requests Unsubscribe!", subscription.from().full().c_str() );
				break;
			 }
		case gloox::Subscription::Unsubscribed: {
				status = _JabberGloox_Subscription_UnSubscribed;
				Log(LOG_INFO, ":handleSubscription(): User %s Unsubscribed!", subscription.from().full().c_str() );
				break;
			 }
		case gloox::Subscription::Invalid: 
		default: {
				Log(LOG_WARNING, ":handleSubscription(): User %s sent invalid subscription request!", subscription.from().full().c_str() );
				break;
			 }
	 }
	if ( this->jabbListener == NULL ) return;
	short ackRequest = this->jabbListener->jabbbot_SubscriptionChanged( subscription.from().full(), status, this );
	if ( ackRequest == -1 ) return; // ignore
	if ( this->xmppJRM == NULL ) {
		Log(LOG_CRITICAL, ":handleSubscription(%s, %d): NULL RosterManager!", subscription.from().full().c_str(), (int)subscription.subtype() );
		return;
	 }
	Log(LOG_INFO, ":handleSubscription(%s, %d): Replying ACK(%d) to subscription", subscription.from().full().c_str(), (int)subscription.subtype(), ackRequest );
	this->xmppJRM->ackSubscriptionRequest(subscription.from().full(), ackRequest);
 }

/////////////////////////////////////////////////////////////////////////////// SubscriptionHandler INTERFACE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool JabberGloox10::setPresence( bool value, bool force ) {
	this->xmppAvailable = value;
	if ( this->xmppJclient != NULL && ( isThreadRunning() || force ) ) {
		Log(LOG_INFO, ":setPresence(%d): Broadcasting new Presence State/Status!", value );
		if ( this->xmppAvailable )
			this->xmppJclient->setPresence(gloox::Presence::Available, this->xmppPriority, this->xmppPresenceStatus);
		else
			this->xmppJclient->setPresence(gloox::Presence::Unavailable, this->xmppPriority, this->xmppPresenceStatus);
		this->xmppJclient->setPresence(); // broadcast it
	 }
	else
		Log(LOG_VERBOSE, ":setPresence(%d): deferred Update to presence value ", value );
	return true;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
